#include "json_file_provider.h"
#include <QFile>
#include <QFileInfo>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QMutexLocker>
#include <QDir>

namespace infrastructure {

JsonFileProvider::JsonFileProvider(const QString& filePath, int priority)
    : m_filePath(filePath)
    , m_priority(priority)
    , m_reloadDelay(100)  // 默认100ms延迟
    , m_watching(false)
    , m_watcher(std::make_unique<QFileSystemWatcher>())
    , m_reloadTimer(std::make_unique<QTimer>()) {
    
    // 设置定时器为单次触发
    m_reloadTimer->setSingleShot(true);
    
    // 连接信号槽
    connect(m_watcher.get(), &QFileSystemWatcher::fileChanged,
            this, &JsonFileProvider::onFileChanged);
    connect(m_reloadTimer.get(), &QTimer::timeout,
            this, &JsonFileProvider::onReloadTimer);
}

JsonFileProvider::~JsonFileProvider() {
    stopWatching();
}

ConfigurationData JsonFileProvider::load() {
    // 读取操作不需要锁，文件IO本身是线程安全的
    // 只有共享状态变量才需要保护
    return loadFromFile();
}

bool JsonFileProvider::isAvailable() const {
    return fileExists();
}

QString JsonFileProvider::getDescription() const {
    return QString("JSON文件配置提供者: %1").arg(m_filePath);
}

void JsonFileProvider::setChangeCallback(ConfigurationChangeCallback callback) {
    QMutexLocker locker(&m_mutex);
    m_callback = callback;
}

void JsonFileProvider::startWatching() {
    QMutexLocker locker(&m_mutex);
    
    if (m_watching) {
        return;
    }
    
    if (!fileExists()) {
        qWarning() << "Cannot watch non-existent file:" << m_filePath;
        return;
    }
    
    // 添加文件到监视器
    if (!m_watcher->files().contains(m_filePath)) {
        m_watcher->addPath(m_filePath);
    }
    
    // 监视文件所在目录（防止文件被删除重建后失去监视）
    QFileInfo fileInfo(m_filePath);
    QString dirPath = fileInfo.absolutePath();
    if (!m_watcher->directories().contains(dirPath)) {
        m_watcher->addPath(dirPath);
    }
    
    m_watching = true;
    
    // 加载初始数据
    m_lastData = loadFromFile();
    
}

void JsonFileProvider::stopWatching() {
    QMutexLocker locker(&m_mutex);
    
    if (!m_watching) {
        return;
    }
    
    // 停止定时器
    m_reloadTimer->stop();
    
    // 移除文件监视
    if (m_watcher->files().contains(m_filePath)) {
        m_watcher->removePath(m_filePath);
    }
    
    // 移除目录监视
    QFileInfo fileInfo(m_filePath);
    QString dirPath = fileInfo.absolutePath();
    if (m_watcher->directories().contains(dirPath)) {
        m_watcher->removePath(dirPath);
    }
    
    m_watching = false;
    
}

int JsonFileProvider::getPriority() const {
    return m_priority;
}

QJsonObject JsonFileProvider::getJsonObject() const {
    // 只读操作不需要锁，文件IO是线程安全的
    return getJsonObjectInternal();
}

QJsonObject JsonFileProvider::getJsonObjectInternal() const {
    // 内部方法，不加锁，由调用者负责线程安全
    if (!fileExists()) {
        return QJsonObject();
    }
    
    QFile file(m_filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "Cannot open config file:" << m_filePath << "Error:" << file.errorString();
        return QJsonObject();
    }
    
    QByteArray data = file.readAll();
    file.close();
    
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(data, &error);
    
    if (doc.isNull()) {
        qWarning() << "JSON解析失败:" << m_filePath << "错误:" << error.errorString();
        return QJsonObject();
    }
    
    if (!doc.isObject()) {
        qWarning() << "JSON根元素不是对象:" << m_filePath;
        return QJsonObject();
    }
    
    return doc.object();
}

void JsonFileProvider::onFileChanged(const QString& path) {
    Q_UNUSED(path)
    
    // 使用定时器避免频繁重载
    m_reloadTimer->start(m_reloadDelay);
}

void JsonFileProvider::onReloadTimer() {
    QMutexLocker locker(&m_mutex);
    
    if (!m_watching || !m_callback) {
        return;
    }
    
    // 重新添加文件监视（某些操作可能会移除监视）
    if (!m_watcher->files().contains(m_filePath) && fileExists()) {
        m_watcher->addPath(m_filePath);
    }
    
    // 加载新数据
    ConfigurationData newData = loadFromFile();
    
    // 比较数据变化并通知
    for (auto iter = newData.values.begin(); iter != newData.values.end(); ++iter) {
        const QString& key = iter.key();
        const QVariant& newValue = iter.value();
        
        if (!m_lastData.values.contains(key) || m_lastData.values[key] != newValue) {
            try {
                m_callback(key, newValue);
            } catch (const std::exception& e) {
                qWarning() << "配置变更回调执行失败:" << e.what();
            }
        }
    }
    
    // 检查已删除的键
    for (auto iter = m_lastData.values.begin(); iter != m_lastData.values.end(); ++iter) {
        const QString& key = iter.key();
        if (!newData.values.contains(key)) {
            try {
                m_callback(key, QVariant());  // 空值表示键被删除
            } catch (const std::exception& e) {
                qWarning() << "配置变更回调执行失败:" << e.what();
            }
        }
    }
    
    m_lastData = newData;
    
}

ConfigurationData JsonFileProvider::loadFromFile() {
    // 这个方法应该在已锁定的上下文中调用
    ConfigurationData result;
    
    if (!fileExists()) {
        qWarning() << "配置文件不存在:" << m_filePath;
        return result;
    }
    
    QJsonObject jsonObj = getJsonObjectInternal();  // 使用内部方法，避免死锁
    if (jsonObj.isEmpty()) {
        return result;
    }
    
    // 递归解析JSON对象
    parseJsonObject(jsonObj, "", result.values);
    
    return result;
}

void JsonFileProvider::parseJsonObject(const QJsonObject& obj, const QString& prefix, QHash<QString, QVariant>& result) {
    for (auto iter = obj.begin(); iter != obj.end(); ++iter) {
        QString key = prefix.isEmpty() ? iter.key() : prefix + ":" + iter.key();
        QJsonValue value = iter.value();

        if (value.isObject()) {
            // 递归处理嵌套对象
            parseJsonObject(value.toObject(), key, result);
        } else if (value.isArray()) {
            // 处理数组：支持索引访问
            QJsonArray array = value.toArray();

            // 存储数组长度
            result[key + ":length"] = array.size();

            // 为数组中的每个元素创建索引访问
            for (int i = 0; i < array.size(); ++i) {
                QString indexKey = key + ":" + QString::number(i);
                QJsonValue arrayValue = array.at(i);

                if (arrayValue.isObject()) {
                    // 如果数组元素是对象，递归解析
                    parseJsonObject(arrayValue.toObject(), indexKey, result);
                } else if (arrayValue.isArray()) {
                    // 嵌套数组，递归处理
                    parseJsonObject(QJsonObject{{QString::number(i), arrayValue}}, key, result);
                } else {
                    // 基本类型直接存储
                    result[indexKey] = arrayValue.toVariant();
                }
            }

            // 同时保留原有的逗号分隔字符串格式（向后兼容）
            QStringList stringList;
            for (const QJsonValue& arrayValue : array) {
                if (arrayValue.isString()) {
                    stringList.append(arrayValue.toString());
                } else {
                    stringList.append(QJsonDocument(QJsonArray{arrayValue}).toJson(QJsonDocument::Compact));
                }
            }
            result[key] = stringList.join(",");
        } else {
            // 基本类型直接存储
            result[key] = value.toVariant();
        }
    }
}

bool JsonFileProvider::fileExists() const {
    QFileInfo fileInfo(m_filePath);
    return fileInfo.exists() && fileInfo.isFile();
}

QDateTime JsonFileProvider::getLastModified() const {
    QFileInfo fileInfo(m_filePath);
    return fileInfo.lastModified();
}

bool JsonFileProvider::createDirectoryIfNeeded() const {
    QFileInfo fileInfo(m_filePath);
    QDir dir = fileInfo.absoluteDir();
    if (!dir.exists()) {
        return dir.mkpath(".");
    }
    return true;
}

bool JsonFileProvider::writeToFile(const QHash<QString, QVariant>& data) {
    // 文件写入操作不需要重锁，文件系统会处理并发写入
    
    if (!createDirectoryIfNeeded()) {
        qWarning() << "Failed to create directory for config file:" << m_filePath;
        return false;
    }
    
    QJsonObject rootObj = createJsonObject(data);
    QJsonDocument doc(rootObj);
    
    QFile file(m_filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "Failed to open config file for writing:" << m_filePath << file.errorString();
        return false;
    }
    
    qint64 bytesWritten = file.write(doc.toJson());
    file.close();
    
    if (bytesWritten == -1) {
        qWarning() << "Failed to write config file:" << m_filePath;
        return false;
    }
    
    return true;
}

bool JsonFileProvider::updateValue(const QString& key, const QVariant& value) {
    
    // 加载当前数据
    ConfigurationData currentData = load();
    
    // 更新值
    currentData.values[key] = value;
    
    // 写回文件
    bool result = writeToFile(currentData.values);
    
    return result;
}

bool JsonFileProvider::removeValue(const QString& key) {
    // 加载当前数据
    ConfigurationData currentData = load();
    
    // 删除键
    currentData.values.remove(key);
    
    // 写回文件
    return writeToFile(currentData.values);
}

bool JsonFileProvider::saveData(const ConfigurationData& data) {
    return writeToFile(data.values);
}

QJsonObject JsonFileProvider::createJsonObject(const QHash<QString, QVariant>& data) {
    QJsonObject rootObj;
    
    for (auto iter = data.begin(); iter != data.end(); ++iter) {
        const QString& key = iter.key();
        const QVariant& value = iter.value();
        
        setJsonValue(rootObj, key, value);
    }
    
    return rootObj;
}

void JsonFileProvider::setJsonValue(QJsonObject& obj, const QString& key, const QVariant& value) {
    // 处理嵌套键（如 "Section:SubSection:Key"）
    QStringList keyParts = key.split(':', Qt::SkipEmptyParts);
    
    // 使用递归方式正确处理嵌套对象
    setJsonValueRecursive(obj, keyParts, 0, value);
}

void JsonFileProvider::setJsonValueRecursive(QJsonObject& obj, const QStringList& keyParts, int index, const QVariant& value) {
    
    if (index == keyParts.size() - 1) {
        // 到达最终键，设置值
        QString finalKey = keyParts[index];
        
        if (value.type() == QVariant::Bool) {
            obj.insert(finalKey, value.toBool());
        } else if (value.type() == QVariant::Int) {
            obj.insert(finalKey, value.toInt());
        } else if (value.type() == QVariant::Double) {
            obj.insert(finalKey, value.toDouble());
        } else if (value.type() == QVariant::String) {
            obj.insert(finalKey, value.toString());
        } else if (value.type() == QVariant::StringList) {
            QJsonArray array;
            QStringList stringList = value.toStringList();
            for (const QString& str : stringList) {
                array.append(str);
            }
            obj.insert(finalKey, array);
        } else {
            // 其他类型转换为字符串
            obj.insert(finalKey, value.toString());
        }
        
    } else {
        // 中间路径，需要创建或获取子对象
        QString currentKey = keyParts[index];
        QJsonObject subObj;
        
        if (obj.contains(currentKey) && obj.value(currentKey).isObject()) {
            subObj = obj.value(currentKey).toObject();
        } else {
        }
        
        // 递归设置子对象
        setJsonValueRecursive(subObj, keyParts, index + 1, value);
        
        // 将修改后的子对象重新插入父对象
        obj.insert(currentKey, subObj);
    }
}

} // namespace infrastructure 